package bupt.xixi.registry.impl;

import bupt.xixi.enumeration.RpcError;
import bupt.xixi.exception.RpcException;
import bupt.xixi.netty.NettyServer;
import bupt.xixi.registry.IServiceRegistry;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;

@Slf4j
abstract public class AbstractRegistry implements IServiceRegistry {

    /**
     * 缓存本服务器上跑的所有服务
     * 接口名：实现类
      */
    private final HashMap<String, Object> serviceMap = new HashMap<>();

    @SneakyThrows
    @Override
    public <T> void registryService(T service) {
        // 请求传来实现类的全限定名
        String serviceName = service.getClass().getCanonicalName();
        // 找到这个实现类实现的所有接口
        Class<?>[] interfaces = service.getClass().getInterfaces();
        if (interfaces.length == 0) {
            log.error("接口不存在！错误！");
        }
        for (Class<?> i : interfaces) {
            // 将每个接口注册进serviceMap<interface的全限定名, 具体的服务实现类的对象>
            serviceMap.put(i.getCanonicalName(), service);
            // 向服务中心注册这个接口
            final String host = InetAddress.getLocalHost().getHostAddress();
            InetSocketAddress inetSocketAddress = InetSocketAddress.createUnresolved(host, NettyServer.PORT);
            doRegistry(i.getCanonicalName(), inetSocketAddress);
        }
        log.info("向接口{}，注册服务{}", interfaces, serviceName);
    }

    @Override
    public Object getService(String InterfaceName) {
        Object service = serviceMap.get(InterfaceName);
        if (service == null) {
            log.error("发生异常，找不到这个实现类");
            throw new RpcException(RpcError.SERVICE_NOT_FOUND);
        }
        return service;
    }

    // todo: 钩子的原理要了解一下的!
    public void shutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread(this::doShutdownHook));
    }

    protected abstract void doRegistry(String serviceName, InetSocketAddress inetSocketAddress);

    protected abstract void doShutdownHook();
}
